package fr.lelouet.ServersModel.virtual.baseimpl;

import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;

import fr.lelouet.ServersModel.physical.DataCenter;
import fr.lelouet.ServersModel.virtual.Allocation;
import fr.lelouet.ServersModel.virtual.VirtualMachine;
import fr.lelouet.ServersModel.virtual.VirtualServer;

/**
 * Simple Allocation implementation that contains a map, and return it in an
 * unmodifiable way.
 * @author le louet
 */
public class SAllocation implements Allocation {

  protected DataCenter center;

  @Override
  public DataCenter getDataCenter() {
    return center;
  }

  public HashMap<VirtualMachine, VmStates> states = new HashMap<VirtualMachine, VmStates>();

  public HashMap<VirtualMachine, VirtualServer> positions = new HashMap<VirtualMachine, VirtualServer>();

  public HashMap<VirtualServer, Set<VirtualMachine>> containment = new HashMap<VirtualServer, Set<VirtualMachine>>();

  public SAllocation(DataCenter center) {

  }

  /** @return a mutable set of the machines on a server with specified state */
  protected Set<VirtualMachine> getMachinesWithState(VirtualServer server,
      VmStates state) {
    Set<VirtualMachine> set = containment.get(server);
    if (set == null) {
      return Collections.emptySet();
    }
    HashSet<VirtualMachine> ret = new HashSet<VirtualMachine>();
    for (VirtualMachine vm : set) {
      if (states.get(vm) == state) {
        ret.add(vm);
      }
    }
    return ret;
  }

  @Override
  public Set<VirtualMachine> getRunningMachines(VirtualServer server) {
    return getMachinesWithState(server, VmStates.Running);
  }

  @Override
  public Set<VirtualMachine> getSTDMachines(VirtualServer server) {
    return getMachinesWithState(server, VmStates.STD);
  }

  @Override
  public Set<VirtualMachine> getSTRMachines(VirtualServer server) {
    return getMachinesWithState(server, VmStates.STR);
  }

  @Override
  public Map<VirtualMachine, VirtualServer> getVMsPositions() {
    return Collections.unmodifiableMap(positions);
  }

  @Override
  public Map<VirtualMachine, VmStates> getVMsStates() {
    return Collections.unmodifiableMap(states);
  }

  public void putVMOnServer(VirtualMachine vm, VirtualServer server) {
    VirtualServer oldServer = positions.get(vm);
    if (oldServer != null) {
      containment.get(oldServer).remove(vm);
    }
    positions.put(vm, server);
    Set<VirtualMachine> contains = containment.get(server);
    if (contains == null) {
      contains = new HashSet<VirtualMachine>();
      containment.put(server, contains);
    }
    contains.add(vm);
  }

  public void putVMOnsState(VirtualMachine vm, VmStates state) {
    states.put(vm, state);
  }

}
